# app.py (Flask application)
from flask import Flask, render_template, request, redirect, url_for, jsonify
import subprocess
import threading
import time
import platform
import os
import logging
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///servers.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# 配置日志
logging.basicConfig(filename='app.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 定义Server模型
class Server(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    hostname = db.Column(db.String(80), nullable=False)
    bmc_ip = db.Column(db.String(120), nullable=False)
    username = db.Column(db.String(80), nullable=False)
    password = db.Column(db.String(80), nullable=False)
    use_lanplus = db.Column(db.Boolean, nullable=False)
    powerstat = db.Column(db.String(20), nullable=False, default='Unknown')

# 初始化数据库
with app.app_context():
    db.create_all()

def get_ipmitool_path(tool_name):
    if platform.system() == 'Windows':
        # 返回 ./ipmitool-win 目录中 ipmitool.exe 的路径
        return os.path.join(os.getcwd(), 'ipmitool-win', f'{tool_name}.exe')
    else:
        # 使用系统中的 ipmitool 命令
        return tool_name

def check_tool_exists(tool_name):
    try:
        if platform.system() == 'Windows':
            # 检查 ./ipmitool-win 目录中是否存在 ipmitool.exe
            tool_path = os.path.join(os.getcwd(), 'ipmitool-win', f'{tool_name}.exe')
            output = os.path.isfile(tool_path)
        else:
            # 使用 'which' 命令在 Unix-like 系统上检查工具
            output = subprocess.check_output(['which', tool_name], stderr=subprocess.STDOUT)

        if output:
            return True
        return False
    except subprocess.CalledProcessError as e:
        # Command not found or other error
        return False

@app.route('/check-tool')
def check_tool():
    tool_name = request.args.get('tool')
    exists = check_tool_exists(tool_name)
    return jsonify({'exists': exists})

# 查询电源状态
def update_power_status():
    with app.app_context():
        while True:
            servers = Server.query.all()
            for server in servers:
                ipmitool_path = get_ipmitool_path('ipmitool')
                logging.info(ipmitool_path)  # 记录命令结果到日志文件

                cmd = [
                    ipmitool_path,
                    '-I', 'lanplus' if server.use_lanplus else 'lan',
                    '-H', server.bmc_ip,
                    '-U', server.username,
                    '-P', server.password,
                    'power', 'status'
                ]
                try:
                    result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
                    if 'Power is on' in result.stdout:
                        server.powerstat = 'power on'
                    elif 'Power is off' in result.stdout:
                        server.powerstat = 'power off'
                    else:
                        logging.info(result.stdout)  # 记录命令结果到日志文件
                        server.powerstat = 'Unknown'
                    db.session.commit()
                except subprocess.TimeoutExpired:
                    server.powerstat = 'Unknown'
            time.sleep(10)

# 启动后台线程更新电源状态
threading.Thread(target=update_power_status, daemon=True).start()

@app.route('/')
def index():
    servers = Server.query.all()
    return render_template('index.html', servers=servers)

@app.route('/add', methods=['GET', 'POST'])
def add_server():
    if request.method == 'POST':
        hostname = request.form['hostname']
        bmc_ip = request.form['bmc_ip']
        username = request.form['username']
        password = request.form['password']
        use_lanplus = request.form.get('use_lanplus') == 'on'
        new_server = Server(hostname=hostname, bmc_ip=bmc_ip, username=username, password=password, use_lanplus=use_lanplus)
        db.session.add(new_server)
        db.session.commit()
        return redirect(url_for('index'))
    return render_template('add_server.html')

@app.route('/edit/<int:id>', methods=['GET', 'POST'])
def edit_server(id):
    server = Server.query.get_or_404(id)
    if request.method == 'POST':
        server.hostname = request.form['hostname']
        server.bmc_ip = request.form['bmc_ip']
        server.username = request.form['username']
        server.password = request.form['password']
        server.use_lanplus = request.form.get('use_lanplus') == 'on'
        db.session.commit()
        return redirect(url_for('index'))
    return render_template('edit_server.html', server=server)

@app.route('/delete/<int:id>', methods=['POST'])
def delete_server(id):
    server = Server.query.get_or_404(id)
    db.session.delete(server)
    db.session.commit()
    return redirect(url_for('index'))

@app.route('/power/<int:id>/<action>')
def power_action(id, action):
    server = Server.query.get_or_404(id)
    if server:
        ipmitool_path = get_ipmitool_path('ipmitool')
        cmd = [
            ipmitool_path,
            '-I', 'lanplus' if server.use_lanplus else 'lan',
            '-H', server.bmc_ip,
            '-U', server.username,
            '-P', server.password,
            'power', action
        ]
        try:
            subprocess.run(cmd, capture_output=True, text=True, timeout=10)
        except subprocess.TimeoutExpired:
            pass
    return redirect(url_for('index'))
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8900, debug=True)
